﻿//暂时没什么改动
#pragma once

#include <qobject.h>
#include <qbytearray.h>
#include <qvector.h>
#include <qtimer.h>
#include <qhash.h>

#include "ACT/LogSaver.h"
#include "ObjAutoInject.h"
class SerialPortManager;
class TurnTableCodec :public QObject, public ObjAutoInject
{
	Q_OBJECT

		//各个标志位
public:
	enum DataPackageHead//转台数据包头部
	{
		TurnTable_DeviceNum = 0xdd,//转台号
		TurnTable_NoAxleNum = 0x00,//无轴号
		TurnTable_AxleNumOne = 0x01//轴号1
	};

	enum TurnTableInstructionFlag {//转台指令标记
		TurnTable_Connect = 0x55,//连接转台
		TurnTable_Disconnect = 0xaa,//关闭转台远控
		TurnTable_SetLoad = 0x01,//设置负载
		TurnTable_PowerOn = 0x03,//上电
		TurnTable_PowerOff = 0x04,//下电
		TurnTable_CloseCircuit = 0x05,//闭合
		TurnTable_OpenCircuit = 0x06,//闲置
		TurnTable_Stop = 0x07,//停止
		TurnTable_EmergencyStop = 0x08,//急停
		TurnTable_SearchZero = 0x09,//寻零
		TurnTable_MoveToZero = 0x0a,//回零
		TurnTable_SetPositionMode = 0x0b,//设置位置模式
		TurnTable_SetRateMode = 0x0c,//设置速率模式
		TurnTable_Run = 0x10,//运行
		TurnTable_CurrentState = 0x13,//查询现场数据
		TurnTable_SearchZeroState = 0x15,//寻零状态
		TurnTable_RunningState = 0x16,//查询转台运行状态
		TurnTable_RunningMode = 0x17,//查询转台运行模式
		Thermostat_Connect = 0x40,//连接温箱
		Thermostat_Disconnect = 0x41,//断开温箱连接
		Thermostat_TargetTemperature = 0x42,//设置温箱目标温度
		Thermostat_CurrentTemperature = 0x43,//查询温箱当前温度
		Thermostat_TemperatureRate = 0x44,//设置温箱变温速率
		TurnTable_QuitConsole = 0xc0,//退出转台控制台
		TurnTable_Error = 0xcc//转台错误
	};
	enum ErrorFlag {//转台错误标记
		Error_ProcessState = 0x01,//过程状态错误
		Error_AxleState = 0x02,//轴状态错误
		Error_AxleNum = 0x03,//轴号错误
		Error_CheckSummation = 0x04,//检查和错误
		Error_TurnTableAddress = 0x05,//转台地址错误
		Error_Load = 0x08,//负载错误
		Error_PositionModeOverLimited = 0x11,//位置模式超限
		Error_RateModeOverLimited = 0x12,//速率模式超限
		Error_OtherUnfitCondition = 0x18,//其他不符合条件的错误
		Error_ThermostatTargetTemperatureFailed = 0x1b,//温箱目标温度设置失败
		Error_ThermostatTargetTemperatureOverLimited = 0x1c,//转台目标温度超限
		Error_ThermostatFeedbackError = 0x1d,//转台反馈错误
		Error_Connection = 0x90//转台连接出错
	};

	enum TurnTableLoadMode {//负载模式
		Mode_Unloaded = 0,//空载模式
		Mode_Loaded = 1//负载模式
	};

	enum TurnTableRunningMode
	{//转台运行模式
		Mode_PositionMode = 1,
		Mode_RateMode = 2
	};

	enum TurnTableRunningState
	{//转台运行状态
		State_TurnTableRunning = 1,
		State_TurnTableStoped = 0
	};
	enum TurnTablePowerSupplyState
	{
		State_PowerOn = 1,
		State_PowerOff = 0
	};
	enum TurnTableCircuitState
	{
		State_CircuitClosed = 1,
		State_CircuitOpened = 0
	};
	enum TurnTableAmplifierState
	{
		State_AmplifierBroken = 1,
		State_AmplifierNormal = 0
	};
	enum TargetState
	{
		State_NotReached = 0,
		State_Reached = 1
	};
	enum ConnectionState
	{//连接状态
		State_Disconnected,
		State_Connected,
		State_Connecting
	};
	enum TurnTableSearchZeroState
	{//转台寻零状态
		State_NotSearch = 0,
		State_Searching = 1,
		State_Searched = 2
	};
	struct InstructionArg
	{
		TurnTableInstructionFlag turnTableInstructionFlag;
		float arg1;
		float arg2;
		float arg3;
	};
private:
	QTimer timer_sendInstruction;//发送指令用的计时器
	int timeInterval_sendInstruction = 30;//发送指令间隔30毫秒，不建议修改，不能低于20毫秒，但过高可能会导致程序无法正常运行，建议不大于50
	QVector<InstructionArg> instructionQueue;//发送指令队列
	QByteArray dataBuffer;//数据缓冲区
	QHash<int, QByteArray(TurnTableCodec::*)(float, float, float)> codeFunMap;//编码函数映射
	QHash<int, void(TurnTableCodec::*)()> decodeFunMap;//解码函数映射

	int dataPackageSize = 16;//数据包长度，单位：字节

	float turnTablePositionUpperLimit = 360;//转台位置上限（绝对值）
	float turnTablePositionLowerLimit = 0;//转台位置下限（绝对值）
	float turnTableRateUpperLimit = 5000;//转台速率上限（绝对值）
	float turnTableRateLowerLimit = 1;//转台速率下限（绝对值）
	float turnTableAccelerationUpperLimit = 100;//转台加速度上限（绝对值）
	float turnTableAccelerationLowerLimit = 1;//转台加速度下限（绝对值）

	SerialPortManager* serialPortManager = Q_NULLPTR;//使用的串口管理器
	LogSaver* logSaver = LogSaver::getLogSaver();
public:
	explicit TurnTableCodec(QObject* parent = Q_NULLPTR);
	virtual ~TurnTableCodec();
signals:
	//转台连接状态信号
	void signal_turnTableConnectionState(ConnectionState connectionState);
	//转台现场数据信号
	void signal_turnTableCurrentState(float position, float rate);
	//转台寻零状态信号
	void signal_turnTableSearchZeroState(TurnTableSearchZeroState turnTableSearchZeroState);
	//转台目标位置状态信号（处于位置模式才有意义）
	void signal_turnTableTargetPositionState(TargetState targetState);
	//转台目标速率状态信号（处于速率模式才有意义）
	void signal_turnTableTargetRateState(TargetState targetState);
	//转台目标停止状态信号（下达停止命令后才有意义）
	void signal_turnTableTargetStop(TargetState targetState);
	//转台电源状态
	void signal_turnTablePowerState(TurnTablePowerSupplyState turnTablePowerSupplyState);
	//转台电路状态
	void signal_turnTableCircuitState(TurnTableCircuitState turnTableCircuitState);
	//转台功放状态
	void signal_turnTableAmplifierState(TurnTableAmplifierState turnTableAmplifierState);
	//转台运行状态
	void signal_turnTableRunningState(TurnTableRunningState turnTableRunningState);
	//转台运行模式
	void signal_turnTableRunningMode(TurnTableRunningMode turnTableRunningMode);
	//温箱当前温度
	void signal_currentThermostatTemperature(float temperature);
	//转台错误信号
	void signal_turnTableError(ErrorFlag errorFlag);
	//转台指令回显
	void signal_instructionEcho(TurnTableInstructionFlag instructionFlag, float arg1, float arg2, float arg3);


	public slots://组装并发送指令
	bool sendInstruction(TurnTableInstructionFlag instructionFlag, float arg1, float arg2, float arg3);
private://指令编码函数
	QByteArray code(char axleNum, char instructionFlag, float data1, float data2, float data3);
	QByteArray code(char axleNum, char instructionFlag);
	QByteArray code(char axleNum, char instructionFlag, int data1);
	QByteArray code(InstructionArg instructionArg);
	QByteArray codeFun_TurnTable_Connect(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_Disconnect(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_SetLoad(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_PowerOn(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_PowerOff(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_CloseCircuit(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_OpenCircuit(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_Stop(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_EmergencyStop(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_SearchZero(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_MoveToZero(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_SetPositionMode(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_SetRateMode(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_Run(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_CurrentState(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_SearchZeroState(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_RunningState(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_RunningMode(float arg1, float arg2, float arg3);
	QByteArray codeFun_Thermostat_Connect(float arg1, float arg2, float arg3);
	QByteArray codeFun_Thermostat_Disconnect(float arg1, float arg2, float arg3);
	QByteArray codeFun_Thermostat_TargetTemperature(float arg1, float arg2, float arg3);
	QByteArray codeFun_Thermostat_CurrentTemperature(float arg1, float arg2, float arg3);
	QByteArray codeFun_Thermostat_TemperatureRate(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_QuitConsole(float arg1, float arg2, float arg3);
	QByteArray codeFun_TurnTable_Error(float arg1, float arg2, float arg3);


	public slots://解码指令数据
	void decode(QByteArray instruction);
private://指令解码函数
	void decode();
	void decode_body();
	void decodeFun_TurnTable_Connect();
	void decodeFun_TurnTable_Disconnect();
	void decodeFun_Thermostat_CurrentTemperature();
	void decodeFun_TurnTable_CurrentState();
	void decodeFun_TurnTable_SearchZeroState();
	void decodeFun_TurnTable_RunningState();
	void decodeFun_TurnTable_RunningMode();
	void decodeFun_TurnTable_Error();

	//代码优化，模块化
private:

	void checkRunningState();
	bool checkDataPackageTurnTableDeviceNum();

	void dataBufferDropData(int byteCount);
	void addCheckSummation(QByteArray* instruction);
	void setZeroInBehind(QByteArray* instruction);
	void addInstructionHead(QByteArray* instruction, char axleNum, char instructionFlag);
	void addDataBody(QByteArray* instruction, int data);
	void addDataBody(QByteArray* instruction, float data);
	bool checkCheckSummation();
	void addToInstructionQueue(InstructionArg instructionArg);


	int dataBodyToInt(int dataBodyNum);
	float dataBodyToFloat(int dataBodyNum);
	//将转台通讯中的先低后高的四字节数据位转换为整形
	int char4ToInt(char* data);

	//将整形转换为转台通讯中的先低后高的四字节数据位
	char* intToChar4(int data, char* data1);
	private slots:
	void slot_timer_sendInstruction_timeOut();

	//getter and setter
public:
	float getTurnTablePositionUpperLimit();
	void setTurnTablePositionUpperLimit(float turnTablePositionUpperLimit);
	float getTurnTablePositionLowerLimit();
	void setTurnTablePositionLowerLimit(float turnTablePositionLowerLimit);
	float getTurnTableRateUpperLimit();
	void setTurnTableRateUpperLimit(float turnTableRateUpperLimit);
	float getTurnTableRateLowerLimit();
	void setTurnTableRateLowerLimit(float turnTableRateLowerLimit);
	float getTurnTableAccelerationUpperLimit();
	void setTurnTableAccelerationUpperLimit(float turnTableAccelerationUpperLimit);
	float getTurnTableAccelerationLowerLimit();
	void setTurnTableAccelerationLowerLimit(float turnTableAccelerationLowerLimit);
public://dependency getter and setter
	SerialPortManager* getSerialPortManager();
	void setSerialPortManager(SerialPortManager* serialPortManager);
public:
	virtual void objectAutoInjection(QHash<QString, QObject*>* objMap)override;
};

//#endif // TURNTABLECODEC_H